﻿using System;
using System.Collections;
using System.Text;
using System.Windows.Forms;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;

namespace TfsCatalogBrowser
{
    public partial class Form1 : Form
    {
        private readonly IDictionary _hasExpanded = new Hashtable();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            foreach (var configServer in RegisteredTfsConnections.GetConfigurationServers())
            {
                ConfigurationServer.Items.Add(configServer.Uri);
            }

            if (ConfigurationServer.Items.Count > 0)
            {
                ConfigurationServer.SelectedIndex = 0;
            }

        }

        private void Connect_Click(object sender, EventArgs e)
        {
            ICatalogService catalogService;
            try
            {
                var uri = new Uri(ConfigurationServer.Text);
                var server = new TfsConfigurationServer(uri);
                server.EnsureAuthenticated();
                catalogService = server.GetService<ICatalogService>();
            }
            catch(Exception ex)
            {
                MessageBox.Show(this, ex.ToString());
                return;
            }
            Text = string.Format("TFS Catalog Browser: {0}", ConfigurationServer.Text);

            _hasExpanded.Clear();
            treeView1.BeginUpdate();
            treeView1.Nodes.Clear();
            foreach (var catalogNode in catalogService.RootNodes)
            {
                AddCatalogNode(treeView1.Nodes, catalogNode);
            }
            treeView1.EndUpdate();
        }

        private void AddCatalogNode(TreeNodeCollection treeNodeCollection, CatalogNode catalogNode)
        {
            var label = GetCatalogNodeLabel(catalogNode);
            var treeNode = treeNodeCollection.Add(catalogNode.FullPath, label);
            treeNode.Tag = catalogNode;
            treeNode.Nodes.Add(treeNode.Name + "_PLACEHOLDER", "Expanding...");
        }

        private static string GetCatalogNodeLabel(CatalogNode catalogNode)
        {
            return string.Format("{0}: {1}", catalogNode.Resource.ResourceType.DisplayName, catalogNode.Resource.DisplayName);
        }

        private void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            lock (_hasExpanded.SyncRoot)
            {
                if (_hasExpanded.Contains(e.Node.Name)) return;
                _hasExpanded.Add(e.Node.Name, null);

                treeView1.BeginUpdate();
                e.Node.Nodes.Clear();
                var catalogNode = (CatalogNode) e.Node.Tag;
                foreach (var childCatalogNode in catalogNode.QueryChildren(null, false, CatalogQueryOptions.ExpandDependencies))
                {
                    AddCatalogNode(e.Node.Nodes, childCatalogNode);
                }

                treeView1.EndUpdate();
            }
        }

        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            var catalogNode = (CatalogNode) e.Node.Tag;
            NodeInfo.Text = string.Format(@"CatalogNode FullPath: {0}
CatalogNode IsDefault: {1}

CatalogResource Description: {2}
CatalogResource DisplayName: {3}
CatalogResource Identifier: {4}

ResourceType Description: {5}
ResourceType DisplayName: {6}
ResourceType Identifier: {7}

", 
 catalogNode.FullPath, 
 catalogNode.IsDefault, 
 catalogNode.Resource.Description, 
 catalogNode.Resource.DisplayName, 
 catalogNode.Resource.Identifier,
 catalogNode.Resource.ResourceType.Description,
 catalogNode.Resource.ResourceType.DisplayName,
 catalogNode.Resource.ResourceType.Identifier);

            ResourceProperties.BeginUpdate();
            ResourceProperties.Items.Clear();
            foreach (var property in catalogNode.Resource.Properties)
            {
                ResourceProperties.Items.Add(property.Key).SubItems.Add(property.Value);
            }
            ResourceProperties.EndUpdate();

            ServiceReferences.BeginUpdate();
            ServiceReferences.Items.Clear();
            foreach (var service in catalogNode.Resource.ServiceReferences)
            {
                var item = ServiceReferences.Items.Add(service.Key);
                item.SubItems.Add(service.Value.Identifier.ToString());
                item.SubItems.Add(service.Value.DisplayName);
                item.SubItems.Add(service.Value.ServiceType);
                item.SubItems.Add(service.Value.ToolType);
                item.SubItems.Add(service.Value.RelativePath);
                item.SubItems.Add(service.Value.RelativeToSetting.ToString());
                item.SubItems.Add("TODO: LocationMappings");
            }
            ServiceReferences.EndUpdate();

            NodeReferences.BeginUpdate();
            NodeReferences.Items.Clear();
            foreach (var node in catalogNode.Resource.NodeReferences)
            {
                var item = NodeReferences.Items.Add(node.FullPath);
                item.SubItems.Add(GetCatalogNodeLabel(node));
            }
            NodeReferences.EndUpdate();

            var builder = new StringBuilder();
            if (catalogNode.Dependencies != null)
            {
                builder.AppendLine("Singletons:");
                foreach (var singleton in catalogNode.Dependencies.Singletons)
                {
                    builder.AppendFormat("Key: {0}, Node: {1}", singleton.Key, GetCatalogNodeLabel(singleton.Value));
                    builder.AppendLine();
                }
                builder.AppendLine();
                builder.AppendLine("Sets:");
                foreach (var set in catalogNode.Dependencies.Sets)
                {
                    builder.AppendFormat("Key: {0}, Nodes:", set.Key);
                    builder.AppendLine();
                    foreach (var node in set.Value)
                    {
                        builder.AppendFormat("  Label: {0}", GetCatalogNodeLabel(node));
                        builder.AppendLine();
                    }
                }
            }

            Other.Text = builder.ToString();
        }

    }
}
